from qwen_vqa import post_extract
from qwen_vqa import query_with_image
import pygame
from flask import Flask, request, jsonify
import os
import threading
from PyQt5.QtWidgets import QApplication, QLabel, QVBoxLayout, QWidget, QTextEdit, QSlider
from PyQt5.QtGui import QPixmap, QFont
import queue
import time
from PyQt5.QtCore import QThread, pyqtSignal, Qt
from VolcanoTTS import get_audio

app = Flask(__name__)

UPLOAD_FOLDER = 'uploads'
os.makedirs(UPLOAD_FOLDER, exist_ok=True)

# Create a message queue to pass image paths
# image_queue = queue.Queue()
message_queue = queue.Queue()

# Global variable to manage a single get_response call at a time
response_in_progress = False


@app.route('/upload', methods=['POST'])
def upload_file():
    try:
        if 'image' not in request.files:
            return jsonify({'error': 'No image file'}), 400

        file = request.files['image']
        if file.filename == '':
            return jsonify({'error': 'No selected file'}), 400

        # 直接从内存中读取文件内容，而不保存到磁盘
        file_content = file.read()

        # 获取其他数据
        code = request.form.get('code', '')
        wrongCardInfoStr = request.form.get('wrongCardInfo', '')
        wrongCardInfo = eval(wrongCardInfoStr)

        wrong_info_description = ""
        for info in wrongCardInfo:
            wrong_info_description += f"名称为 {info['card']} 的卡片 错误地出现在正确答案为{info['target']}的target上\n"

        # 将数据放入队列，使用BytesIO对象替代文件路径
        from io import BytesIO
        image_buffer = BytesIO(file_content)
        message_queue.put((image_buffer, code, wrong_info_description))

        return jsonify({'message': 'Data received successfully'}), 200

    except Exception as e:
        print("Upload error:", str(e))
        return jsonify({'error': str(e)}), 500


def run_flask():
    # Run Flask server
    app.run(host='0.0.0.0', port=6200, threaded=True)


def get_prompt(code, wrong_info):
    # Foo implementation of getting prompt (e.g., from a model or API)

    prefix_prompt = f"""You will output with JSON format.
    老师写了一个早教游戏

游戏的代码如下

{code}。 

现在学生在操作过程中出现了失误，结果的图片如下，"""

    suffix_prompt = f"""程序的错误提示为:{wrong_info}

请你模仿老师的口吻，给学生一定的提示（20个词以内），帮助学生进一步完成这道题
如果这是一个数学题，但是出现等号后错误，可以用“ new_a + b才等于 wrong_ans 哦，再想想a+b等于几”的口吻来引导

Let's think it step-by-step and output into JSON format
- analysis: 先分析小朋友出现了什么错误
- guide: 针对小朋友出现的错误，给出20个词以内的提示
"""
    return prefix_prompt, suffix_prompt


def get_response(input_data):
    # Simulate a time-consuming task (e.g., calling a model)
    prefix_prompt, suffix_prompt, image_path = input_data
    # time.sleep(5)
    try:
        response = query_with_image(image_path, prefix_prompt, suffix_prompt)
        return response
    except Exception as e:
        return str(e)


class ResponseWorker(QThread):
    # Signal to pass response back to main thread
    response_signal = pyqtSignal(str)

    def __init__(self, prompt):
        super().__init__()
        self.prompt = prompt

    def run(self):
        global response_in_progress
        if not response_in_progress:
            response_in_progress = True
            response = get_response(self.prompt)
            # Emit signal to update UI
            self.response_signal.emit(response)
            response_in_progress = False


def play_audio(mp3_path):
    # 使用合适的音频播放库来播放生成的 mp3 文件

    pygame.mixer.init()
    pygame.mixer.music.load(mp3_path)
    pygame.mixer.music.play()


def update_image():
    global response_in_progress

    app = QApplication([])
    window = QWidget()
    layout = QVBoxLayout()
    label = QLabel()
    guide_box = QTextEdit()
    response_box = QTextEdit()
    prompt_box = QTextEdit()

    guide_box.setText("Guide 字体大小测试")
    response_box.setText("Response 字体大小测试")
    prompt_box.setText("Prompt 字体大小测试")

    def adjust_font_size(value):
        font = QFont()
        font.setPointSize(value)
        guide_box.setFont(font)
        response_box.setFont(font)
        prompt_box.setFont(font)

    # 创建 QSlider 控件
    slider = QSlider(Qt.Horizontal)
    slider.setMinimum(8)  # 最小字体大小
    slider.setMaximum(120)  # 最大字体大小
    slider.setValue(14)  # 初始字体大小
    slider.valueChanged.connect(adjust_font_size)  # 连接槽函数

    def got_response(response):
        response_box.setText(response)
        guide_str = ""
        try:
            extracted_data = post_extract(response)
            if "guide" in extracted_data:
                guide_box.setText(extracted_data["guide"])
                guide_str = extracted_data["guide"]
            else:
                guide_box.setText("Failed to parse guide")
        except Exception as e:
            print("Error parsing response:", e)
            pass

        if guide_str != "":
            mp3_path = get_audio(guide_str)
            play_audio(mp3_path)

    layout.addWidget(label)
    layout.addWidget(guide_box)
    layout.addWidget(prompt_box)
    layout.addWidget(response_box)
    layout.addWidget(slider)

    window.setLayout(layout)
    window.show()

    while True:
        # Check if there are new images in the queue
        if not message_queue.empty():
            image_buffer, code, wrong_info = message_queue.get()

            # 从BytesIO创建QPixmap
            image_data = image_buffer.getvalue()
            pixmap = QPixmap()
            pixmap.loadFromData(image_data)

            # Resize image to have a height of 600, maintaining the aspect ratio
            pixmap = pixmap.scaledToHeight(600)

            label.setPixmap(pixmap)
            label.adjustSize()

            # Get the prompt and display it in the prompt box
            prefix_prompt, suffix_prompt = get_prompt(code, wrong_info)
            prompt_box.setText(prefix_prompt + "\n" + suffix_prompt)

            # Start async call to get response
            if not response_in_progress:
                worker = ResponseWorker(
                    (prefix_prompt, suffix_prompt, image_buffer))
                worker.response_signal.connect(got_response)
                worker.start()

        app.processEvents()


if __name__ == '__main__':
    # Start Flask server in a separate thread
    flask_thread = threading.Thread(target=run_flask)
    flask_thread.daemon = True
    flask_thread.start()

    # Start the PyQt image display and response handling
    update_image()
